home *** CD-ROM | disk | FTP | other *** search
- /* (C) Copyright 1991 Andrew Plotkin. Permission is
- given to copy and use, as long as this copyright
- notice is retained. */
-
- #include <stdio.h>
- #include <math.h>
- #include <X11/Xlib.h>
- #include "spatial.h"
-
- typedef struct _cubep {
- int x, y, z;
- } cubep;
-
- point plist[MAXPOINTS]; /* shape, arbitrarily rotated */
- point traplist[MAXPOINTS]; /* plist + offsets */
- point templist[MAXCUBES]; /* temporary version */
- double offx, offy, offz;
- double focallen, boardscale;
- int halfboard, halfboard2;
- fieldplist fieldpts;
- fieldplist fieldpts2;
-
- int colors[11] = {1, 3, 4, 7, 9, 10, 11, 12, 13, 14, 15};
-
- extern GC gcblack, gcwhite, gcinv, gccopy, gcline, gccubes[];
-
- extern void updatepiece(), setup_fieldpm();
- extern void add_one_cubie(), update_meter();
-
- void startpiece()
- {
- piecelist *p;
- register int ix;
- int res;
- double flix, fliy, fliz;
-
- curpiece = random() % numpieces;
- flix = (random()%2)*2-1;
- fliy = (random()%2)*2-1;
- fliz = (random()%2)*2-1;
-
- p = &(pieces[curpiece]);
- for (ix=0; ix<p->numpoints; ix++) {
- plist[ix].x = flix*p->points[ix].x;
- plist[ix].y = fliy*p->points[ix].y;
- plist[ix].z = fliz*p->points[ix].z;
- plist[ix].w = p->points[ix].w;
- traplist[ix].w = plist[ix].w;
- };
- offx=0.0;
- offy=0.0;
- offz=(double)fieldz+5.0;
- updatepiece();
- res = collision(0);
- while (res>=1 && res<=6) {
- switch (res) {
- case 1:
- offz = floor(offz - 1.0 + 0.5);
- break;
- case 2:
- fprintf(stderr,
- "spatial: piece too long for board\n");
- exit(-1);
- break;
- case 3:
- offy = floor(offy + 1.0 + 0.5);
- break;
- case 4:
- offy = floor(offy - 1.0 + 0.5);
- break;
- case 5:
- offx = floor(offx - 1.0 + 0.5);
- break;
- case 6:
- offx = floor(offx + 1.0 + 0.5);
- break;
- }
- updatepiece();
- res = collision(0);
- };
- if (res==(-1)) curpiece = (-2);
- }
-
- void rotate_piece(axis, theta) /* works on plist */
- int axis;
- double theta;
- {
- register int ix;
- double t1, t2;
- double sinth = sin(theta);
- double costh = cos(theta);
-
- switch (axis) {
- case 1:
- for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
- t1 = plist[ix].y;
- t2 = plist[ix].z;
- plist[ix].y = costh*t1 - sinth*t2;
- plist[ix].z = sinth*t1 + costh*t2;
- }
- break;
- case 2:
- for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
- t1 = plist[ix].x;
- t2 = plist[ix].z;
- plist[ix].x = costh*t1 - sinth*t2;
- plist[ix].z = sinth*t1 + costh*t2;
- }
- break;
- case 3:
- for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
- t1 = plist[ix].x;
- t2 = plist[ix].y;
- plist[ix].x = costh*t1 - sinth*t2;
- plist[ix].y = sinth*t1 + costh*t2;
- }
- break;
- }
- }
-
- void updatepiece() /* create traplist from plist+offsets */
- {
- register int ix;
-
- for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
- traplist[ix].x = plist[ix].x + offx;
- traplist[ix].y = plist[ix].y + offy;
- traplist[ix].z = plist[ix].z + offz;
- };
- }
-
- void updatetemp_tra(xa, ya, za, taxi, tdir)
- short xa, ya, za, taxi, tdir;
- {
- register int ix;
-
- switch (taxi) {
- case 0:
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- templist[ix].x = traplist[ix].x;
- templist[ix].y = traplist[ix].y;
- templist[ix].z = traplist[ix].z;
- };
- break;
- case 1:
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- templist[ix].x = plist[ix].x + offx;
- templist[ix].y = -tdir*plist[ix].z + offy;
- templist[ix].z = tdir*plist[ix].y + offz;
- };
- break;
- case 2:
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- templist[ix].x = -tdir*plist[ix].z + offx;
- templist[ix].y = plist[ix].y + offy;
- templist[ix].z = tdir*plist[ix].x + offz;
- };
- break;
- case 3:
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- templist[ix].x = -tdir*plist[ix].y + offx;
- templist[ix].y = tdir*plist[ix].x + offy;
- templist[ix].z = plist[ix].z + offz;
- };
- break;
- }
-
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- templist[ix].x += (double)xa;
- templist[ix].y += (double)ya;
- templist[ix].z += (double)za;
- };
- }
-
- void round_piece() /* round off piece to int
- offsets, halfint coords */
- {
- register int ix;
-
- offx = floor(offx+0.5);
- offy = floor(offy+0.5);
- offz = floor(offz+0.5);
-
- for (ix=0; ix<pieces[curpiece].numpoints; ix++) {
- plist[ix].x = floor(2.0*plist[ix].x + 0.5)/2.0;
- plist[ix].y = floor(2.0*plist[ix].y + 0.5)/2.0;
- plist[ix].z = floor(2.0*plist[ix].z + 0.5)/2.0;
- };
- }
-
- int collision(listflag)
- /* returns (in this priority)
- 1: out-of-field up;
- 2: ...down;
- 3: ...north;
- 4: ...south;
- 5: ...east;
- 6: ...west;
- -1 for cube overlap;
- 0 for ok;
- */
- int listflag;
- {
- register int ix;
- cubep cubes[MAXCUBES];
- point *pls;
-
- if (listflag==0) pls = traplist;
- else pls = templist;
-
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- cubes[ix].x = (int)(pls[ix].x+100.0) - 100;
- cubes[ix].y = (int)(pls[ix].y+100.0) - 100;
- cubes[ix].z = (int)(pls[ix].z+100.0) - 100;
-
- if (cubes[ix].z < 0) return 2;
- if (cubes[ix].z >= fieldz) return 1;
- if (cubes[ix].y < 0) return 3;
- if (cubes[ix].y >= fieldy) return 4;
- if (cubes[ix].x >= fieldx) return 5;
- if (cubes[ix].x < 0) return 6;
- };
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- if (field[cubes[ix].x][cubes[ix].y][cubes[ix].z] & F_ON)
- return (-1);
- };
- return 0;
- }
-
- void setup_cubies()
- {
- register int ix, iy, iz;
- double wcoord;
-
- for (ix=0; ix<=fieldx; ix++)
- for (iy=0; iy<=fieldy; iy++)
- for (iz=0; iz<=fieldz; iz++) {
- wcoord = -((double)iz+fieldoffz)/focallen + 1.0;
- fieldpts[ix][iy][iz].x = halfboard +
- (int)(boardscale*((double)ix+fieldoffx)/wcoord);
- fieldpts[ix][iy][iz].y = halfboard +
- (int)(boardscale*((double)iy+fieldoffy)/wcoord);
- }
-
- if (stereo) {
- for (ix=0; ix<=fieldx; ix++)
- for (iy=0; iy<=fieldy; iy++)
- for (iz=0; iz<=fieldz; iz++) {
- wcoord = -((double)iz+fieldoffz)/focallen + 1.0;
- fieldpts2[ix][iy][iz].x = halfboard2 +
- (int)(boardscale*((double)ix+fieldoffx2) / wcoord);
- fieldpts2[ix][iy][iz].y = halfboard +
- (int)(boardscale*((double)iy+fieldoffy) / wcoord);
- }
- }
- }
-
- void add_cubie(cx, cy, cz)
- int cx, cy, cz;
- {
- add_one_cubie(fieldpts, cx, cy, cz);
- if (stereo)
- add_one_cubie(fieldpts2, cx, cy, cz);
- }
-
- void add_one_cubie(fips, cx, cy, cz)
- fieldplist fips;
- int cx, cy, cz;
- {
- int x1, y1, width, heigh;
- XPoint face[5];
- GC *gcc;
-
- gcc = &(gccubes[colors[cz]]);
- x1 = fips[cx][cy][cz+1].x;
- y1 = fips[cx][cy][cz+1].y;
- width = fips[cx+1][cy+1][cz+1].x - x1 + 1;
- heigh = fips[cx+1][cy+1][cz+1].y - y1 + 1;
- XFillRectangle(dpy, fieldpm, *gcc, x1, y1, width, heigh);
- XDrawRectangle(dpy, fieldpm, gcwhite, x1, y1, width, heigh);
-
- x1 = cx - fieldx/2;
- if (x1<0) {
- face[0].x = fips[cx+1][cy][cz+1].x;
- face[0].y = fips[cx+1][cy][cz+1].y;
- face[1].x = fips[cx+1][cy][cz].x;
- face[1].y = fips[cx+1][cy][cz].y;
- face[2].x = fips[cx+1][cy+1][cz].x;
- face[2].y = fips[cx+1][cy+1][cz].y;
- face[3].x = fips[cx+1][cy+1][cz+1].x;
- face[3].y = fips[cx+1][cy+1][cz+1].y;
- face[4].x = face[0].x;
- face[4].y = face[0].y;
- XFillPolygon(dpy, fieldpm, *gcc, face, 4,
- Convex, CoordModeOrigin);
- XDrawLines(dpy, fieldpm, gcwhite, face, 5,
- CoordModeOrigin);
- }
- else if (x1>0) {
- face[0].x = fips[cx][cy][cz+1].x;
- face[0].y = fips[cx][cy][cz+1].y;
- face[1].x = fips[cx][cy][cz].x;
- face[1].y = fips[cx][cy][cz].y;
- face[2].x = fips[cx][cy+1][cz].x;
- face[2].y = fips[cx][cy+1][cz].y;
- face[3].x = fips[cx][cy+1][cz+1].x;
- face[3].y = fips[cx][cy+1][cz+1].y;
- face[4].x = face[0].x;
- face[4].y = face[0].y;
- XFillPolygon(dpy, fieldpm, *gcc, face, 4,
- Convex, CoordModeOrigin);
- XDrawLines(dpy, fieldpm, gcwhite, face, 5,
- CoordModeOrigin);
- };
-
- y1 = cy - fieldy/2;
- if (y1>0) {
- face[0].x = fips[cx][cy][cz+1].x;
- face[0].y = fips[cx][cy][cz+1].y;
- face[1].x = fips[cx][cy][cz].x;
- face[1].y = fips[cx][cy][cz].y;
- face[2].x = fips[cx+1][cy][cz].x;
- face[2].y = fips[cx+1][cy][cz].y;
- face[3].x = fips[cx+1][cy][cz+1].x;
- face[3].y = fips[cx+1][cy][cz+1].y;
- face[4].x = face[0].x;
- face[4].y = face[0].y;
- XFillPolygon(dpy, fieldpm, *gcc, face, 4,
- Convex, CoordModeOrigin);
- XDrawLines(dpy, fieldpm, gcwhite, face, 5,
- CoordModeOrigin);
- }
- else if (y1<0) {
- face[0].x = fips[cx][cy+1][cz+1].x;
- face[0].y = fips[cx][cy+1][cz+1].y;
- face[1].x = fips[cx][cy+1][cz].x;
- face[1].y = fips[cx][cy+1][cz].y;
- face[2].x = fips[cx+1][cy+1][cz].x;
- face[2].y = fips[cx+1][cy+1][cz].y;
- face[3].x = fips[cx+1][cy+1][cz+1].x;
- face[3].y = fips[cx+1][cy+1][cz+1].y;
- face[4].x = face[0].x;
- face[4].y = face[0].y;
- XFillPolygon(dpy, fieldpm, *gcc, face, 4,
- Convex, CoordModeOrigin);
- XDrawLines(dpy, fieldpm, gcwhite, face, 5,
- CoordModeOrigin);
- };
- }
-
- void add_cubies(lev)
- int lev;
- {
- register int ix, iy, iz;
-
- for (iz=lev; iz<fieldz; iz++) {
- for (ix=0; ix<fieldx/2; ix++) {
- for (iy=0; iy<fieldy/2; iy++) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- for (iy=fieldy-1; iy>=fieldy/2; iy--) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- }
- for (ix=fieldx-1; ix>=fieldx/2; ix--) {
- for (iy=0; iy<fieldy/2; iy++) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- for (iy=fieldy-1; iy>=fieldy/2; iy--) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- }
- };
- if (meterlev != meteroldlev) {
- update_meter();
- }
- }
-
- void redraw_cubies()
- {
- register int ix, iy, iz;
-
- for (iz=0; iz<fieldz; iz++) {
- for (ix=0; ix<fieldx/2; ix++) {
- for (iy=0; iy<fieldy/2; iy++) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- for (iy=fieldy-1; iy>=fieldy/2; iy--) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- }
- for (ix=fieldx-1; ix>=fieldx/2; ix--) {
- for (iy=0; iy<fieldy/2; iy++) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- for (iy=fieldy-1; iy>=fieldy/2; iy--) {
- if (field[ix][iy][iz] & F_ON) {
- add_cubie(ix, iy, iz);
- }
- }
- }
- }
- if (meterlev != meteroldlev) {
- update_meter();
- }
- }
-
- void plop_piece()
- {
- register int ix, iy, iz;
- int cubx, cuby, cubz;
- int dirx, diry;
- int lev = fieldz+1;
-
- for (ix=0; ix<pieces[curpiece].numcubes; ix++) {
- cubx = (int)(traplist[ix].x+100.0) - 100;
- cuby = (int)(traplist[ix].y+100.0) - 100;
- cubz = (int)(traplist[ix].z+100.0) - 100;
- if (cubz < lev) lev = cubz;
- if (cubz+1 > meterlev) meterlev = cubz+1;
- field[cubx][cuby][cubz] |= F_ON;
- };
- add_cubies(lev);
-
- /* settle */
- while (1) {
- int full;
- for (iz=fieldz-1; iz>=0; iz--) {
- full=1;
- for (ix=0; full && (ix<fieldx); ix++) {
- for (iy=0; full && (iy<fieldy); iy++) {
- if (!(field[ix][iy][iz] & F_ON)) full = 0;
- }
- }
- if (full) break;
- }
- if (iz<0) break;
- for (; iz<fieldz-1; iz++)
- for (ix=0; ix<fieldx; ix++)
- for (iy=0; iy<fieldy; iy++)
- field[ix][iy][iz] = field[ix][iy][iz+1];
- for (ix=0; ix<fieldx; ix++)
- for (iy=0; iy<fieldy; iy++)
- field[ix][iy][fieldz-1] = 0;
- score += 20*fieldx*fieldy;
- if (dropticks > 10) dropticks -= 6;
- meterlev--;
- setup_fieldpm();
- redraw_cubies();
- }
- }
-
- void draw_curpiece(drw)
- Drawable drw;
- {
- register int ix;
- static point scoor[MAXVERTS];
- static point scoor2[MAXVERTS];
- static XSegment xpl[MAXEDGES*2];
- double wcoord;
- int poff = pieces[curpiece].numcubes;
- int nume = pieces[curpiece].numedges;
- edge *e = pieces[curpiece].edges;
-
- shapex1 = dispx;
- shapex2 = 0;
- shapey1 = dispy;
- shapey2 = 0;
- for (ix=0; ix<pieces[curpiece].numverts; ix++) {
- wcoord = -(traplist[ix+poff].z+fieldoffz)/focallen + 1.0;
- scoor[ix].x = halfboard +
- (int)(boardscale*(traplist[ix+poff].x+fieldoffx)/wcoord);
- scoor[ix].y = halfboard +
- (int)(boardscale*(traplist[ix+poff].y+fieldoffy)/wcoord);
- if (shapex1>scoor[ix].x-1) shapex1=scoor[ix].x-1;
- if (shapey1>scoor[ix].y-1) shapey1=scoor[ix].y-1;
- if (shapex2<scoor[ix].x+1) shapex2=scoor[ix].x+1;
- if (shapey2<scoor[ix].y+1) shapey2=scoor[ix].y+1;
- if (stereo) {
- scoor2[ix].x = halfboard2 +
- (int)(boardscale*(traplist[ix+poff].x+fieldoffx2)
- / wcoord);
- if (shapex2<scoor2[ix].x+1) shapex2=scoor2[ix].x+1;
- }
- }
-
- if (!stereo) {
- for (ix=0; ix<nume; ix++) {
- xpl[ix].x1 = scoor[e[ix].head].x;
- xpl[ix].y1 = scoor[e[ix].head].y;
- xpl[ix].x2 = scoor[e[ix].tail].x;
- xpl[ix].y2 = scoor[e[ix].tail].y;
- }
- XDrawSegments(dpy, drw, gcline, xpl, nume);
- }
- else {
- for (ix=0; ix<nume; ix++) {
- xpl[ix].x1 = scoor[e[ix].head].x;
- xpl[ix].y1 = scoor[e[ix].head].y;
- xpl[ix].x2 = scoor[e[ix].tail].x;
- xpl[ix].y2 = scoor[e[ix].tail].y;
- xpl[nume+ix].x1 = scoor2[e[ix].head].x;
- xpl[nume+ix].y1 = xpl[ix].y1;
- xpl[nume+ix].x2 = scoor2[e[ix].tail].x;
- xpl[nume+ix].y2 = xpl[ix].y2;
- }
- XDrawSegments(dpy, drw, gcline, xpl, 2*nume);
- }
- }
-